<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>日历打卡系统</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  <style>
    body {
      font-family: 'Arial', sans-serif;
      background-color: #f5f5f5;
      padding: 20px;
    }
    .calendar-container {
      max-width: 800px;
      margin: 0 auto;
      background: white;
      border-radius: 10px;
      box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
      overflow: hidden;
    }
    .calendar-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 20px;
      background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
      color: white;
    }
    .calendar-header h2 {
      margin: 0;
      font-size: 1.5rem;
    }
    .calendar-header button {
      background: rgba(255, 255, 255, 0.2);
      border: none;
      color: white;
      padding: 8px 16px;
      border-radius: 4px;
      cursor: pointer;
      font-weight: bold;
      transition: background 0.3s;
    }
    .calendar-header button:hover {
      background: rgba(255, 255, 255, 0.3);
    }
    .calendar-weekdays {
      display: grid;
      grid-template-columns: repeat(7, 1fr);
      background: #f0f0f0;
      font-weight: bold;
      text-align: center;
      padding: 10px 0;
    }
    .calendar-days {
      display: grid;
      grid-template-columns: repeat(7, 1fr);
      gap: 1px;
      background: #e0e0e0;
    }
    .day {
      aspect-ratio: 1;
      background: white;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      position: relative;
      cursor: pointer;
      transition: all 0.2s;
    }
    .day:hover {
      background: #f0f8ff;
    }
    .day-number {
      font-size: 1.2rem;
      font-weight: bold;
    }
    .day.other-month {
      color: #ccc;
      background: #f9f9f9;
    }
    .day.today {
      background: #e6f7ff;
      font-weight: bold;
    }
    .day.checked {
      background: #e8f5e9;
    }
    .day.unchecked {
      background: #ffebee;
    }
    .day.checked::after {
      content: '✓';
      position: absolute;
      bottom: 10px;
      color: #2e7d32;
      font-size: 1.5rem;
      font-weight: bold;
    }
    .day.unchecked::after {
      content: '✗';
      position: absolute;
      bottom: 10px;
      color: #c62828;
      font-size: 1.5rem;
      font-weight: bold;
    }
    .stats {
      padding: 20px;
      background: white;
      margin-top: 20px;
      border-radius: 10px;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    }
    .progress-bar {
      height: 20px;
      background: #f0f0f0;
      border-radius: 10px;
      margin-top: 10px;
      overflow: hidden;
    }
    .progress {
      height: 100%;
      background: linear-gradient(90deg, #6a11cb, #2575fc);
      transition: width 0.5s;
    }
    .legend {
      display: flex;
      justify-content: center;
      margin-top: 15px;
      gap: 20px;
    }
    .legend-item {
      display: flex;
      align-items: center;
    }
    .legend-color {
      width: 20px;
      height: 20px;
      margin-right: 5px;
      border-radius: 3px;
    }
  </style>
</head>
<body>
  <div id="app">
    <div class="calendar-container">
      <div class="calendar-header">
        <button @click="prevMonth">上个月</button>
        <h2>{{ currentYear }}年 {{ currentMonth + 1 }}月</h2>
        <button @click="nextMonth">下个月</button>
      </div>
      
      <div class="calendar-weekdays">
        <div v-for="day in weekdays" :key="day">{{ day }}</div>
      </div>
      
      <div class="calendar-days">
        <div 
          v-for="(day, index) in calendarDays" 
          :key="index"
          :class="[
            'day', 
            { 'other-month': !day.isCurrentMonth },
            { 'today': day.isToday },
            { 'checked': day.checked },
            { 'unchecked': day.isCurrentMonth && !day.isToday && !day.checked && day.date < today }
          ]"
          @click="toggleCheck(day.date)"
        >
          <span class="day-number">{{ day.date.getDate() }}</span>
        </div>
      </div>
    </div>

    <div class="stats">
      <h3>本月打卡统计</h3>
      <p>已打卡: {{ checkedCount }}天 / {{ currentMonthDays }}天</p>
      <div class="progress-bar">
        <div class="progress" :style="{ width: progressPercentage }"></div>
      </div>
      <div class="legend">
        <div class="legend-item">
          <div class="legend-color" style="background: #e8f5e9;"></div>
          <span>已打卡</span>
        </div>
        <div class="legend-item">
          <div class="legend-color" style="background: #ffebee;"></div>
          <span>未打卡</span>
        </div>
        <div class="legend-item">
          <div class="legend-color" style="background: #e6f7ff;"></div>
          <span>今天</span>
        </div>
        <div class="legend-item">
          <div class="legend-color" style="background: #f9f9f9;"></div>
          <span>其他月份</span>
        </div>
      </div>
    </div>
  </div>

  <script>
    new Vue({
      el: '#app',
      data() {
        return {
          weekdays: ['日', '一', '二', '三', '四', '五', '六'],
          currentDate: new Date(),
          today: new Date(),
          checkedDates: JSON.parse(localStorage.getItem('checkedDates')) || []
        }
      },
      computed: {
        currentYear() {
          return this.currentDate.getFullYear();
        },
        currentMonth() {
          return this.currentDate.getMonth();
        },
        currentMonthDays() {
          return new Date(this.currentYear, this.currentMonth + 1, 0).getDate();
        },
        calendarDays() {
          const year = this.currentYear;
          const month = this.currentMonth;
          
          // 获取当月第一天
          const firstDay = new Date(year, month, 1);
          // 获取当月最后一天
          const lastDay = new Date(year, month + 1, 0);
          // 获取当月第一天是星期几 (0-6)
          const firstDayOfWeek = firstDay.getDay();
          // 获取上个月最后一天
          const prevMonthLastDay = new Date(year, month, 0).getDate();
          
          // 获取当月天数
          const daysInMonth = lastDay.getDate();
          
          // 创建日历数组
          const days = [];
          
          // 添加上个月的几天
          for (let i = firstDayOfWeek - 1; i >= 0; i--) {
            const date = new Date(year, month - 1, prevMonthLastDay - i);
            days.push(this.createDayObject(date, false));
          }
          
          // 添加当月的天数
          for (let i = 1; i <= daysInMonth; i++) {
            const date = new Date(year, month, i);
            days.push(this.createDayObject(date, true));
          }
          
          // 添加下个月的几天 (补齐42个格子)
          const remainingDays = 42 - days.length;
          for (let i = 1; i <= remainingDays; i++) {
            const date = new Date(year, month + 1, i);
            days.push(this.createDayObject(date, false));
          }
          
          return days;
        },
        checkedCount() {
          return this.checkedDates.filter(date => {
            const d = new Date(date);
            return d.getFullYear() === this.currentYear && 
                   d.getMonth() === this.currentMonth;
          }).length;
        },
        progressPercentage() {
          return (this.checkedCount / this.currentMonthDays * 100) + '%';
        }
      },
      methods: {
        createDayObject(date, isCurrentMonth) {
          return {
            date,
            isCurrentMonth,
            isToday: this.isToday(date),
            checked: this.isChecked(date)
          };
        },
        isToday(date) {
          return (
            date.getDate() === this.today.getDate() &&
            date.getMonth() === this.today.getMonth() &&
            date.getFullYear() === this.today.getFullYear()
          );
        },
        isChecked(date) {
          return this.checkedDates.some(
            d => new Date(d).toDateString() === date.toDateString()
          );
        },
        toggleCheck(date) {
          if (!date.isCurrentMonth || date > this.today) return;
          
          const dateString = date.toISOString().split('T')[0];
          const index = this.checkedDates.findIndex(
            d => new Date(d).toDateString() === date.toDateString()
          );
          
          if (index === -1) {
            this.checkedDates.push(dateString);
          } else {
            this.checkedDates.splice(index, 1);
          }
          
          // 保存到本地存储
          localStorage.setItem('checkedDates', JSON.stringify(this.checkedDates));
        },
        prevMonth() {
          this.currentDate = new Date(
            this.currentYear,
            this.currentMonth - 1,
            1
          );
        },
        nextMonth() {
          this.currentDate = new Date(
            this.currentYear,
            this.currentMonth + 1,
            1
          );
        }
      }
    });
  </script>
</body>
</html>
